//
//  PercentEscaped.m
//  objective_c_language
//
//  Created by 龙 on 2018/5/25.
//  Copyright © 2018年 longlong. All rights reserved.
//

#import "PercentEscaped.h"
#import "QueryStringPairClass.h"

@implementation PercentEscaped

///百分号编码
NSString * PercentEscapedStringFromString(NSString *string)
{
    static NSString * const kAFCharactersGeneralDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4
    static NSString * const kAFCharactersSubDelimitersToEncode = @"!$&'()*+,;=";
    
    NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
    [allowedCharacterSet removeCharactersInString:[kAFCharactersGeneralDelimitersToEncode stringByAppendingString:kAFCharactersSubDelimitersToEncode]];
    
    // FIXME: https://github.com/AFNetworking/AFNetworking/pull/3028
    // return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];
    
    static NSUInteger const batchSize = 50;
    
    NSUInteger index = 0;
    NSMutableString *escaped = @"".mutableCopy;
    
    while (index < string.length) {
        NSUInteger length = MIN(string.length - index, batchSize);
        NSRange range = NSMakeRange(index, length);
        
        // To avoid breaking up character sequences such as 👴🏻👮🏽
        range = [string rangeOfComposedCharacterSequencesForRange:range];
        
        NSString *substring = [string substringWithRange:range];
        NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];
        [escaped appendString:encoded];
        
        index += range.length;
    }
    
    return escaped;
}

///从字典中查询字符串
NSString * QueryStringFromParameters(NSDictionary *parameters)
{
    NSMutableArray *mutablePairs = [NSMutableArray array];
    for (QueryStringPairClass *pair in QueryStringPairsFromDictionary(parameters))
    {
        [mutablePairs addObject:[pair URLEncodedStringValue]];
    }
    
    return [mutablePairs componentsJoinedByString:@"&"];
}

NSArray * QueryStringPairsFromDictionary(NSDictionary *dictionary) {
    return QueryStringPairsFromKeyAndValue(nil, dictionary);
    //@{@"name":name,@"age":@20};
    //age=20&name=zhangsan
}

NSArray * QueryStringPairsFromKeyAndValue(NSString *key, id value) {
    NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
    
    //排序： 升序
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)];
    
    if ([value isKindOfClass:[NSDictionary class]])
    {
        //@"dict":@{@"name":name,@"age":@20}
        //dict[age]=20&dict[name]=zhangsan
        NSDictionary *dictionary = value;
        NSArray *allKeys = [dictionary.allKeys sortedArrayUsingDescriptors:@[sortDescriptor]];
        for (id nestedKey in allKeys)
        {
            id nestedValue = dictionary[nestedKey];
            if (nestedValue)
            {
                NSString *dictKey = key ? [NSString stringWithFormat:@"%@[%@]",key,nestedKey] : nestedKey;
                [mutableQueryStringComponents addObjectsFromArray:QueryStringPairsFromKeyAndValue(dictKey, nestedValue)];
            }
        }
    }
    else if ([value isKindOfClass:[NSArray class]])
    {
        //@"userInfo":@[@{@"name":name,@"age":@20},@{@"name":name2,@"age":@23}]
        //userInfo[][age]=20&userInfo[][name]=zhangsan&userInfo[][age]=23&userInfo[][name]=lisi
        NSArray *array = value;
        for (id nestedValue in array)
        {
            [mutableQueryStringComponents addObjectsFromArray:QueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
        }
    }
    else if ([value isKindOfClass:[NSSet class]])
    {
        NSSet *set = value;
        for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]])
        {
            [mutableQueryStringComponents addObjectsFromArray:QueryStringPairsFromKeyAndValue(key, obj)];
        }
    }
    else
    {
        //@"name":@"zhangsan"
        //name=zhangsan
        [mutableQueryStringComponents addObject:[[QueryStringPairClass alloc] initWithField:key value:value]];
    }
    
    return mutableQueryStringComponents;
}


@end
